﻿using System;
using System.IO;
using System.Collections;
using System.Text;

public class B3InputStream : B3Input {

	Stream input;

	public int _Read() {
		return input.ReadByte ();
	}

	public static int _Read(Stream input) {
		return input.ReadByte ();
	}

	public byte[] _Read (byte[] buf, int offset, int count)
	{
		input.Read(buf, offset, count);
		return buf;
	}

	public static byte[] _Read (Stream input, byte[] buf, int offset, int count)
	{
		input.Read(buf, offset, count);
		return buf;
	}

	public byte[] _Read (byte[] buf)
	{
		int offset = 0;
		int count = buf.Length;
		return _Read(buf, offset, count);
	}

	public static byte[] _Read (Stream input, byte[] buf)
	{
		int offset = 0;
		int count = buf.Length;
		return _Read(input, buf, offset, count);
	}

	public B3Types _ReadTag() {
		return _ReadTag(input);
	}

	public static B3Types _ReadTag(Stream input) {
		int v = _Read (input);
		if(v < 0)
			throw new EndOfStreamException();
		return (B3Types) v;
	}

	public long skipBytes(int n)
	{
		input.Position += n;
		return input.Position;
	}

	public static long skipBytes(Stream input, int n)
	{
		input.Position += n;
		return input.Position;
	}

	//

	public B3InputStream(Stream input)
	{
		this.input = input;
	}

	public bool ReadBool ()
	{
		return ReadBool(input);
	}

	public static bool ReadBool (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadBool(input, tag);
	}

	public bool ReadBool(B3Types tag) 
	{
		return ReadBool(input, tag);
	}

	public static bool ReadBool(Stream input, B3Types tag) {
		switch (tag) {
		case B3Types.BOOL_TRUE:
			return true;
		case B3Types.BOOL_FALSE:
			return false;
		default:
			throw new IOException("unknow type.");
		}
	}

	public byte ReadByte ()
	{
		return ReadByte(input);
	}

	public static byte ReadByte (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadByte(input, tag);
	}

	public byte ReadByte(B3Types tag)
	{
		return ReadByte(input, tag);
	}

	public static byte ReadByte(Stream input, B3Types tag)
	{
		switch (tag) {
		case B3Types.BYTE_0:
			return 0;
		case B3Types.BYTE:
			return (byte) _Read(input);
		default:
			throw new IOException("unknow type.");
		}
	}
	public int ReadInt ()
	{
		return ReadInt(input);
	}

	public static int ReadInt (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadInt(input, tag);
	}

	public int ReadInt(B3Types tag)
	{
		return ReadInt(input, tag);
	}

	public static int ReadInt(Stream input, B3Types tag)
	{
		switch (tag) {
		case B3Types.INT_N1:
			return -1;
		case B3Types.INT_0:
			return 0;
		case B3Types.INT_1:
			return 1;
		case B3Types.INT_2:
			return 2;
		case B3Types.INT_3:
			return 3;
		case B3Types.INT_4:
			return 4;
		case B3Types.INT_5:
			return 5;
		case B3Types.INT_6:
			return 6;
		case B3Types.INT_7:
			return 7;
		case B3Types.INT_8:
			return 8;
		case B3Types.INT_9:
			return 9;
		case B3Types.INT_10:
			return 10;
		case B3Types.INT_11:
			return 11;
		case B3Types.INT_12:
			return 12;
		case B3Types.INT_13:
			return 13;
		case B3Types.INT_14:
			return 14;
		case B3Types.INT_15:
			return 15;
		case B3Types.INT_16:
			return 16;
		case B3Types.INT_17:
			return 17;
		case B3Types.INT_18:
			return 18;
		case B3Types.INT_19:
			return 19;
		case B3Types.INT_20:
			return 20;
		case B3Types.INT_21:
			return 21;
		case B3Types.INT_22:
			return 22;
		case B3Types.INT_23:
			return 23;
		case B3Types.INT_24:
			return 24;
		case B3Types.INT_25:
			return 25;
		case B3Types.INT_26:
			return 26;
		case B3Types.INT_27:
			return 27;
		case B3Types.INT_28:
			return 28;
		case B3Types.INT_29:
			return 29;
		case B3Types.INT_30:
			return 30;
		case B3Types.INT_31:
			return 31;
		case B3Types.INT_32:
			return 32;
		case B3Types.INT_8B: {
			int v = (sbyte)_Read(input);
			return v;
		}
		case B3Types.INT_16B: {
			int value1 = _Read(input);
			int value2 = _Read(input);
			
			int v = (((value1 & 0xff) << 8) + ((value2 & 0xff) << 0));
			return v;
		}
		case B3Types.INT_32B: {
			int value1 = _Read(input);
			int value2 = _Read(input);
			int value3 = _Read(input);
			int value4 = _Read(input);
			
			int v = ((value1 & 0xff) << 24) + ((value2 & 0xff) << 16)
				+ ((value3 & 0xff) << 8) + ((value4 & 0xff) << 0);
			return v;
		}
		default:
			throw new IOException("unknow type.");
		}
	}

	public long ReadLong ()
	{
		return ReadLong(input);
	}

	public static long ReadLong (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadLong(input, tag);
	}

	public long ReadLong(B3Types tag)
	{
		return ReadLong(input, tag);
	}

	public static long ReadLong(Stream input, B3Types tag)  {
		switch (tag) {
		case B3Types.LONG_0:
			return 0;
		case B3Types.LONG_8B: {
			long v = (sbyte)_Read(input);
			return v;
		}
		case B3Types.LONG_16B: {
			int v0 = _Read(input);
			int v1 = _Read(input);
			long v = (((v0 & 0xff) << 8) + ((v1 & 0xff) << 0));
			return v;
		}
		case B3Types.LONG_32B: {
			int v0 = _Read(input);
			int v1 = _Read(input);
			int v2 = _Read(input);
			int v3 = _Read(input);
			long v = ((v0 & 0xff) << 24) + ((v1 & 0xff) << 16)
				+ ((v2 & 0xff) << 8) + ((v3 & 0xff) << 0);
			return v;
		}
		case B3Types.LONG_64B: {
			int v0 = _Read(input);
			int v1 = _Read(input);
			int v2 = _Read(input);
			int v3 = _Read(input);
			int v4 = _Read(input);
			int v5 = _Read(input);
			int v6 = _Read(input);
			int v7 = _Read(input);
			long high = ((v0 & 0xff) << 24) + ((v1 & 0xff) << 16)
				+ ((v2 & 0xff) << 8) + ((v3 & 0xff) << 0);
			long low = ((v4 & 0xff) << 24) + ((v5 & 0xff) << 16)
				+ ((v6 & 0xff) << 8) + ((v7 & 0xff) << 0);
			long v = (high << 32) + (0xffffffffL & low);
			return v;
		}
		default:
			throw new IOException("unknow type.");
		}
	}
	public double ReadDouble ()
	{
		return ReadDouble(input);
	}

	public static double ReadDouble (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadDouble(input, tag);
	}
	public double ReadDouble(B3Types tag)
	{
		return ReadDouble(input, tag);
	}
	public static double ReadDouble(Stream input, B3Types tag)
	{
		switch (tag) {
		case B3Types.DOUBLE_0:
			return 0;
		case B3Types.DOUBLE_64:
			int v0 = _Read(input);
			int v1 = _Read(input);
			int v2 = _Read(input);
			int v3 = _Read(input);
			int v4 = _Read(input);
			int v5 = _Read(input);
			int v6 = _Read(input);
			int v7 = _Read(input);
			long high = ((v0 & 0xff) << 24) + ((v1 & 0xff) << 16)
				+ ((v2 & 0xff) << 8) + ((v3 & 0xff) << 0);
			long low = ((v4 & 0xff) << 24) + ((v5 & 0xff) << 16)
				+ ((v6 & 0xff) << 8) + ((v7 & 0xff) << 0);
			long v = (high << 32) + (0xffffffffL & low);
			double ret = Int64BitsToDouble(v);
			return ret;
		default:
			throw new IOException("unknow type.");
		}
	}
	public string ReadUTF ()
	{
		return ReadUTF(input);
	}
	public static string ReadUTF (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadUTF(input, tag);
	}
	public string ReadUTF(B3Types tag)
	{
		return ReadUTF(input, tag);
	}
	public static string ReadUTF(Stream input, B3Types tag)
	{
		if (tag == B3Types.NULL)
			return null;
		
		int size = 0;
		switch (tag) {
		case B3Types.UTF8_0:
			return "";
		case B3Types.UTF8_1: {
			size = 1;
			break;
		}
		case B3Types.UTF8_2: {
			size = 2;
			break;
		}
		case B3Types.UTF8_3: {
			size = 3;
			break;
		}
		case B3Types.UTF8_4: {
			size = 4;
			break;
		}
		case B3Types.UTF8_5: {
			size = 5;
			break;
		}
		case B3Types.UTF8_6: {
			size = 6;
			break;
		}
		case B3Types.UTF8_7: {
			size = 7;
			break;
		}
		case B3Types.UTF8_8: {
			size = 8;
			break;
		}
		case B3Types.UTF8_9: {
			size = 9;
			break;
		}
		case B3Types.UTF8_10: {
			size = 10;
			break;
		}
		case B3Types.UTF8_11: {
			size = 11;
			break;
		}
		case B3Types.UTF8_12: {
			size = 12;
			break;
		}
		case B3Types.UTF8_13: {
			size = 13;
			break;
		}
		case B3Types.UTF8_14: {
			size = 14;
			break;
		}
		case B3Types.UTF8_15: {
			size = 15;
			break;
		}
		case B3Types.UTF8_16: {
			size = 16;
			break;
		}
		case B3Types.UTF8_17: {
			size = 17;
			break;
		}
		case B3Types.UTF8_18: {
			size = 18;
			break;
		}
		case B3Types.UTF8_19: {
			size = 19;
			break;
		}
		case B3Types.UTF8_20: {
			size = 20;
			break;
		}
		case B3Types.UTF8_21: {
			size = 21;
			break;
		}
		case B3Types.UTF8_22: {
			size = 22;
			break;
		}
		case B3Types.UTF8_23: {
			size = 23;
			break;
		}
		case B3Types.UTF8_24: {
			size = 24;
			break;
		}
		case B3Types.UTF8_25: {
			size = 25;
			break;
		}
		case B3Types.UTF8_26: {
			size = 26;
			break;
		}
		case B3Types.UTF8_27: {
			size = 27;
			break;
		}
		case B3Types.UTF8_28: {
			size = 28;
			break;
		}
		case B3Types.UTF8_29: {
			size = 29;
			break;
		}
		case B3Types.UTF8_30: {
			size = 30;
			break;
		}
		case B3Types.UTF8_31: {
			size = 31;
			break;
		}
		case B3Types.UTF8_32: {
			size = 32;
			break;
		}
		case B3Types.UTF8: {
			size = ReadInt(input);
			break;
		}
		default: {
			throw new IOException("unknow type.");
		}
		}
		byte[] b = new byte[size];
		_Read(input, b);
		return Encoding.UTF8.GetString (b);
	}
	
	public byte[] ReadBytes ()
	{
		return ReadBytes(input);
	}
	public static byte[] ReadBytes (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadBytes(input, tag);
	}
	public byte[] ReadBytes(B3Types tag)
	{
		return ReadBytes(input, tag);
	}
	public static byte[] ReadBytes(Stream input, B3Types tag)
	{
		if (tag == B3Types.NULL)
			return null;
		else if (tag == B3Types.BYTES_0)
			return new byte[0];
		else if (tag == B3Types.BYTES) {
			int size = ReadInt(input);
			byte[] b = new byte[size];
			_Read(input, b);
			return b;
		} else
			throw new IOException("unknow type.");
	}

	public ArrayList ReadList ()
	{
		return ReadList(input);
	}
	public static ArrayList ReadList (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadList(input, tag);
	}
	public ArrayList ReadList(B3Types tag)
	{
		return ReadList(input, tag);
	}

	public static ArrayList ReadList(Stream input, B3Types tag) {
		if (tag == B3Types.NULL)
			return null;
		int size = 0;
		switch (tag) {
		case B3Types.LIST_0:
			return new ArrayList();
		case B3Types.LIST_1: {
			size = 1;
			break;
		}
		case B3Types.LIST_2: {
			size = 2;
			break;
		}
		case B3Types.LIST_3: {
			size = 3;
			break;
		}
		case B3Types.LIST_4: {
			size = 4;
			break;
		}
		case B3Types.LIST_5: {
			size = 5;
			break;
		}
		case B3Types.LIST_6: {
			size = 6;
			break;
		}
		case B3Types.LIST_7: {
			size = 7;
			break;
		}
		case B3Types.LIST_8: {
			size = 8;
			break;
		}
		case B3Types.LIST_9: {
			size = 9;
			break;
		}
		case B3Types.LIST_10: {
			size = 10;
			break;
		}
		case B3Types.LIST_11: {
			size = 11;
			break;
		}
		case B3Types.LIST_12: {
			size = 12;
			break;
		}
		case B3Types.LIST_13: {
			size = 13;
			break;
		}
		case B3Types.LIST_14: {
			size = 14;
			break;
		}
		case B3Types.LIST_15: {
			size = 15;
			break;
		}
		case B3Types.LIST_16: {
			size = 16;
			break;
		}
		case B3Types.LIST: {
			size = ReadInt(input);
			break;
		}
		default:
			throw new IOException("unknow type.");
		}
		
		ArrayList list = new ArrayList(size);
		for (int i = 0; i < size; i++) {
			Object e = ReadObject(input);
			list.Add(e);
		}
		return list;
	}

	public Hashtable ReadSet ()
	{
		return ReadSet(input);
	}
	public static Hashtable ReadSet (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadSet(input, tag);
	}
	public Hashtable ReadSet(B3Types tag)
	{
		return ReadSet(input, tag);
	}
	public static Hashtable ReadSet(Stream input, B3Types tag)
	{
		if (tag == B3Types.NULL)
			return null;
		int size = 0;
		switch (tag) {
		case B3Types.SET_0:
			return new Hashtable();
		case B3Types.SET:
			size = ReadInt(input);
			break;
		default:
			throw new IOException("unknow type.");
		}
		
		Hashtable set = new Hashtable();
		for (int i = 0; i < size; i++) {
			Object e = ReadObject(input);
			set.Add(e, 0);
		}
		return set;
	}
	public Hashtable ReadMap ()
	{
		return ReadMap(input);
	}

	public static Hashtable ReadMap (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadMap(input, tag);
	}
	public Hashtable ReadMap(B3Types tag)
	{
		return ReadMap(input, tag);
	}
	public static Hashtable ReadMap(Stream input, B3Types tag)
	{
		if (tag == B3Types.NULL)
			return null;
		
		int size = 0;
		switch (tag) {
		case B3Types.MAP_0:
			return new Hashtable();
		case B3Types.MAP_1: {
			size = 1;
			break;
		}
		case B3Types.MAP_2: {
			size = 2;
			break;
		}
		case B3Types.MAP_3: {
			size = 3;
			break;
		}
		case B3Types.MAP_4: {
			size = 4;
			break;
		}
		case B3Types.MAP_5: {
			size = 5;
			break;
		}
		case B3Types.MAP_6: {
			size = 6;
			break;
		}
		case B3Types.MAP_7: {
			size = 7;
			break;
		}
		case B3Types.MAP_8: {
			size = 8;
			break;
		}
		case B3Types.MAP_9: {
			size = 9;
			break;
		}
		case B3Types.MAP_10: {
			size = 10;
			break;
		}
		case B3Types.MAP_11: {
			size = 11;
			break;
		}
		case B3Types.MAP_12: {
			size = 12;
			break;
		}
		case B3Types.MAP_13: {
			size = 13;
			break;
		}
		case B3Types.MAP_14: {
			size = 14;
			break;
		}
		case B3Types.MAP_15: {
			size = 15;
			break;
		}
		case B3Types.MAP_16: {
			size = 16;
			break;
		}
		case B3Types.MAP: {
			size = ReadInt(input);
			break;
		}
		default:
			throw new IOException("unknow type.");
		}
		Hashtable map = new Hashtable(size);
		for (int i = 0; i < size; i++) {
			Object key = ReadObject(input);
			Object value = ReadObject(input);
			map[key] = value;
		}
		return map;
	}
	public System.DateTime ReadDate ()
	{
		return ReadDate(input);
	}
	public static System.DateTime ReadDate (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadDate(input, tag);
	}
	public DateTime ReadDate(B3Types tag)
	{
		return ReadDate(input, tag);
	}
	public static DateTime ReadDate(Stream input, B3Types tag)
	{
		if (tag == B3Types.NULL)
			return DateTime.Now;
		else if (tag == B3Types.DATE) {
			int v0 = _Read(input);
			int v1 = _Read(input);
			int v2 = _Read(input);
			int v3 = _Read(input);
			int v4 = _Read(input);
			int v5 = _Read(input);
			int v6 = _Read(input);
			int v7 = _Read(input);
			long high = ((v0 & 0xff) << 24) + ((v1 & 0xff) << 16)
				+ ((v2 & 0xff) << 8) + ((v3 & 0xff) << 0);
			long low = ((v4 & 0xff) << 24) + ((v5 & 0xff) << 16)
				+ ((v6 & 0xff) << 8) + ((v7 & 0xff) << 0);
			long v = (high << 32) + (0xffffffffL & low);
			
			return JavaDateToDateTime(v);
		} else {
			throw new IOException("unknow type.");
		}
	}

	public int[] ReadIntArray ()
	{
		return ReadIntArray(input);
	}
	public static int[] ReadIntArray (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadIntArray(input, tag);
	}
	public int[] ReadIntArray(B3Types tag)
	{
		return ReadIntArray(input, tag);
	}
	public static int[] ReadIntArray(Stream input, B3Types tag)
	{
		if (tag == B3Types.NULL)
			return null;
		if (tag == B3Types.INT_ARRAY_0)
			return new int[0];
		else if (tag == B3Types.INT_ARRAY) {
			int size = ReadInt(input);
			int[] array = new int[size];
			for (int i = 0; i < size; i++) {
				array[i] = ReadInt(input);
			}
			return array;
		} else {
			throw new IOException("unknow type.");
		}
	}

	public string[] ReadStrArray ()
	{
		return ReadStrArray(input);
	}
	public static string[] ReadStrArray (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadStrArray(input, tag);
	}
	public String[] ReadStrArray(B3Types tag)
	{
		return ReadStrArray(input, tag);
	}
	public static String[] ReadStrArray(Stream input, B3Types tag)
	{
		if (tag == B3Types.NULL)
			return null;
		else if (tag == B3Types.STR_ARRAY_0)
			return new String[0];
		else if (tag == B3Types.STR_ARRAY) {
			int size = ReadInt(input);
			String[] array = new String[size];
			for (int i = 0; i < size; i++) {
				array[i] = ReadUTF(input);
			}
			return array;
		} else
			throw new IOException("unknow type.");
	}

	public object ReadObject ()
	{
		return ReadObject(input);
	}

	public static object ReadObject (Stream input)
	{
		B3Types tag = _ReadTag(input);
		return ReadObject(input, tag);
	}

	public object ReadObject(B3Types tag)
	{
		return ReadObject(input, tag);
	}
	public static object ReadObject(Stream input, B3Types tag)
	{
		if (tag == B3Types.NULL)
			return null;
		
		switch (tag) {
			// boolean
		case B3Types.BOOL_TRUE:
		case B3Types.BOOL_FALSE:
			return ReadBool(input, tag);
			// byte
		case B3Types.BYTE_0:
		case B3Types.BYTE:
			return ReadByte(input, tag);
			// int
		case B3Types.INT_N1:
		case B3Types.INT_0:
		case B3Types.INT_1:
		case B3Types.INT_2:
		case B3Types.INT_3:
		case B3Types.INT_4:
		case B3Types.INT_5:
		case B3Types.INT_6:
		case B3Types.INT_7:
		case B3Types.INT_8:
		case B3Types.INT_9:
		case B3Types.INT_10:
		case B3Types.INT_11:
		case B3Types.INT_12:
		case B3Types.INT_13:
		case B3Types.INT_14:
		case B3Types.INT_15:
		case B3Types.INT_16:
		case B3Types.INT_17:
		case B3Types.INT_18:
		case B3Types.INT_19:
		case B3Types.INT_20:
		case B3Types.INT_21:
		case B3Types.INT_22:
		case B3Types.INT_23:
		case B3Types.INT_24:
		case B3Types.INT_25:
		case B3Types.INT_26:
		case B3Types.INT_27:
		case B3Types.INT_28:
		case B3Types.INT_29:
		case B3Types.INT_30:
		case B3Types.INT_31:
		case B3Types.INT_32:
		case B3Types.INT_8B:
		case B3Types.INT_16B:
		case B3Types.INT_32B:
			return ReadInt(input, tag);
			// long
		case B3Types.LONG_0:
		case B3Types.LONG_8B:
		case B3Types.LONG_16B:
		case B3Types.LONG_32B:
		case B3Types.LONG_64B:
			return ReadLong(input, tag);
			// double
		case B3Types.DOUBLE_0:
		case B3Types.DOUBLE_64:
			return ReadDouble(input, tag);
			// String
		case B3Types.UTF8_0:
		case B3Types.UTF8_1:
		case B3Types.UTF8_2:
		case B3Types.UTF8_3:
		case B3Types.UTF8_4:
		case B3Types.UTF8_5:
		case B3Types.UTF8_6:
		case B3Types.UTF8_7:
		case B3Types.UTF8_8:
		case B3Types.UTF8_9:
		case B3Types.UTF8_10:
		case B3Types.UTF8_11:
		case B3Types.UTF8_12:
		case B3Types.UTF8_13:
		case B3Types.UTF8_14:
		case B3Types.UTF8_15:
		case B3Types.UTF8_16:
		case B3Types.UTF8_17:
		case B3Types.UTF8_18:
		case B3Types.UTF8_19:
		case B3Types.UTF8_20:
		case B3Types.UTF8_21:
		case B3Types.UTF8_22:
		case B3Types.UTF8_23:
		case B3Types.UTF8_24:
		case B3Types.UTF8_25:
		case B3Types.UTF8_26:
		case B3Types.UTF8_27:
		case B3Types.UTF8_28:
		case B3Types.UTF8_29:
		case B3Types.UTF8_30:
		case B3Types.UTF8_31:
		case B3Types.UTF8_32:
		case B3Types.UTF8:
			return ReadUTF(input, tag);
			// byte[]
		case B3Types.BYTES_0:
		case B3Types.BYTES:
			return ReadBytes(input, tag);
			// List
		case B3Types.LIST_0:
		case B3Types.LIST_1:
		case B3Types.LIST_2:
		case B3Types.LIST_3:
		case B3Types.LIST_4:
		case B3Types.LIST_5:
		case B3Types.LIST_6:
		case B3Types.LIST_7:
		case B3Types.LIST_8:
		case B3Types.LIST_9:
		case B3Types.LIST_10:
		case B3Types.LIST_11:
		case B3Types.LIST_12:
		case B3Types.LIST_13:
		case B3Types.LIST_14:
		case B3Types.LIST_15:
		case B3Types.LIST_16:
		case B3Types.LIST:
			return ReadList(input, tag);
			// Set
		case B3Types.SET_0:
		case B3Types.SET:
			return ReadSet(input, tag);
			// Map
		case B3Types.MAP_0:
		case B3Types.MAP_1:
		case B3Types.MAP_2:
		case B3Types.MAP_3:
		case B3Types.MAP_4:
		case B3Types.MAP_5:
		case B3Types.MAP_6:
		case B3Types.MAP_7:
		case B3Types.MAP_8:
		case B3Types.MAP_9:
		case B3Types.MAP_10:
		case B3Types.MAP_11:
		case B3Types.MAP_12:
		case B3Types.MAP_13:
		case B3Types.MAP_14:
		case B3Types.MAP_15:
		case B3Types.MAP_16:
		case B3Types.MAP:
			return ReadMap(input, tag);
			// Date
		case B3Types.DATE:
			return ReadDate(input, tag);
			// int[]
		case B3Types.INT_ARRAY_0:
		case B3Types.INT_ARRAY:
			return ReadIntArray(input, tag);
			// String[]
		case B3Types.STR_ARRAY_0:
		case B3Types.STR_ARRAY:
			return ReadStrArray(input, tag);
		default:
			throw new IOException("unknow type.");
		}
	}
	//
	static double Int64BitsToDouble (long v)
	{
		try {
			return BitConverter.Int64BitsToDouble (v);
		} catch {
			return 0;
		}
	}

	static DateTime JavaDateToDateTime (long x)
	{
		DateTime dat0 = new DateTime(1970, 1, 1, 8, 0, 0);
		long tm = (x + dat0.Ticks / 10000) * 10000;
		return new DateTime (tm);
	}

}
